use std::any::Any;
use std::time::Duration;
use async_trait::async_trait;
use tokio::time::sleep;

use protoactor_rs::actor::{Actor, ActorContext, ActorError, DefaultActorContext, Props};
use protoactor_rs::system::ActorSystem;

// 定义几种不同的消息类型
#[derive(Debug, Clone)]
struct Ping {
    count: u32,
}

#[derive(Debug, Clone)]
struct Pong {
    count: u32,
}

#[derive(Debug, Clone)]
struct Add {
    a: i32,
    b: i32,
}

#[derive(Debug, Clone)]
struct Echo {
    message: String,
}

// 定义一个可以处理多种消息类型的Actor
#[derive(Clone)]
struct MessageHandler {
    name: String,
}

#[async_trait]
impl Actor for MessageHandler {
    type Context = DefaultActorContext;

    // 处理不同类型的消息
    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn Any + Send>) -> Result<(), ActorError> {
        println!("[{}] Received a message, type_id: {:?}", self.name, msg.type_id());
        
        // 尝试匹配不同类型的消息
        if let Some(ping) = msg.downcast_ref::<Ping>() {
            println!("[{}] Received Ping message with count: {}", self.name, ping.count);
            
            // 回复一个Pong消息
            let pong = Pong { count: ping.count + 1 };
            println!("[{}] Responding with Pong: {}", self.name, pong.count);
            
            // 添加延迟，模拟处理时间
            sleep(Duration::from_millis(100)).await;
            
            // 发送响应
            ctx.respond(pong);
            println!("[{}] Pong response sent", self.name);
        } 
        else if let Some(add) = msg.downcast_ref::<Add>() {
            println!("[{}] Received Add message: {} + {}", self.name, add.a, add.b);
            
            // 计算结果并回复
            let result = add.a + add.b;
            println!("[{}] Responding with result: {}", self.name, result);
            
            // 添加延迟，模拟处理时间
            sleep(Duration::from_millis(100)).await;
            
            // 发送响应
            ctx.respond(result);
            println!("[{}] Add result sent", self.name);
        }
        else if let Some(echo) = msg.downcast_ref::<Echo>() {
            println!("[{}] Received Echo message: {}", self.name, echo.message);
            
            // 回显消息
            let response = format!("Echo from {}: {}", self.name, echo.message);
            println!("[{}] Responding with: {}", self.name, response);
            
            // 添加延迟，模拟处理时间
            sleep(Duration::from_millis(100)).await;
            
            // 发送响应
            ctx.respond(response);
            println!("[{}] Echo response sent", self.name);
        }
        else {
            println!("[{}] Received unknown message type: {:?}", self.name, msg.type_id());
        }
        
        Ok(())
    }
    
    // Actor启动时调用
    async fn started(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Actor started", self.name);
        Ok(())
    }
    
    // Actor停止时调用
    async fn stopping(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Actor stopping", self.name);
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    println!("Starting message passing example");
    
    // 创建actor系统
    let system = ActorSystem::new().unwrap();
    println!("Actor system created");
    
    // 创建一个MessageHandler Actor
    let props = Props::from_producer(|| MessageHandler { 
        name: "Handler1".to_string() 
    });
    let handler_pid = system.spawn::<MessageHandler>(props).await?;
    println!("MessageHandler spawned with PID: {:?}", handler_pid);
    
    // 等待Actor启动
    sleep(Duration::from_millis(100)).await;
    println!("\n--- Testing Ping message ---");
    
    // 发送Ping消息并等待Pong响应
    let ping = Ping { count: 1 };
    println!("Sending Ping message to actor...");
    match system.request::<Pong>(&handler_pid, ping, Duration::from_secs(5)).await {
        Ok(pong) => println!("Received Pong response: count = {}", pong.count),
        Err(e) => println!("Error receiving Pong response: {:?}", e),
    }
    
    // 等待一段时间
    sleep(Duration::from_millis(500)).await;
    println!("\n--- Testing Add message ---");
    
    // 发送Add消息并等待结果
    let add = Add { a: 5, b: 7 };
    println!("Sending Add message to actor...");
    match system.request::<i32>(&handler_pid, add, Duration::from_secs(5)).await {
        Ok(result) => println!("Received Add result: {}", result),
        Err(e) => println!("Error receiving Add result: {:?}", e),
    }
    
    // 等待一段时间
    sleep(Duration::from_millis(500)).await;
    println!("\n--- Testing Echo message ---");
    
    // 发送Echo消息并等待回显
    let echo = Echo { message: "Hello, Actor!".to_string() };
    println!("Sending Echo message to actor...");
    match system.request::<String>(&handler_pid, echo, Duration::from_secs(5)).await {
        Ok(response) => println!("Received Echo response: {}", response),
        Err(e) => println!("Error receiving Echo response: {:?}", e),
    }
    
    // 等待一段时间
    sleep(Duration::from_millis(100)).await;
    
    // 停止Actor
    println!("\nStopping MessageHandler");
    system.stop(&handler_pid).await?;
    
    // 等待Actor停止
    sleep(Duration::from_secs(1)).await;
    println!("Example completed successfully");
    
    Ok(())
} 